package com.atguigu.tingshu.user.service.impl;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;
    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;
    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;
    @Autowired
    private UserVipServiceMapper userVipServiceMapper;
    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Override

    public Map<String, Object> wxLogin(String code) {
        //创建一个map
        Map<String, Object> map = new HashMap<>();
        //	获取微信服务器中的openId;   System.getenv(); 可以获取系统环境中的变量;
        WxMaJscode2SessionResult wxMaJscode2SessionResult = null;
        // 获取openId
        try {
            wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(code);
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        //openId 是每一个用户的表示符
        String openId = wxMaJscode2SessionResult.getOpenid();
        //获取用户信息
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openId));
        //判断用户信息是否为空 则注册创建用户 然后发送消息(送福利 送金币)
        if (null == userInfo) {
            userInfo = new UserInfo();
            userInfo.setWxOpenId(openId);
            userInfo.setNickname("神仙" + System.currentTimeMillis());
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            userInfoMapper.insert(userInfo);
            log.info("用户信息插入成功");
            //送福利发金币 消息队列    1.远程调用 / 2.异步编排
            rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
        }
        //数据库存在 把数据添加到缓存中
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
        redisTemplate.opsForValue().set(userLoginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.DAYS);
        //存储数据
        map.put("token", token);
        return map;
    }

    @Override
    public UserInfoVo getUserInfo(Long userId) {
        //	创建一个UserInfoVo对象
        UserInfoVo userInfoVo = new UserInfoVo();
        //	查询用户信息表;
        UserInfo userInfo = this.getById(userId);
        //	属性拷贝：
        BeanUtils.copyProperties(userInfo, userInfoVo);
        return userInfoVo;
    }

    @Override
    public void updateUser(UserInfoVo userInfoVo, Long userId) {
        //
        UserInfo userInfo = new UserInfo();
        userInfoVo.setId(userId);
        BeanUtils.copyProperties(userInfoVo, userInfo);
        //更新用户数据
        userInfoMapper.updateById(userInfo);
    }

    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdNeedPaidList, Long userId) {
        //	创建map 集合;
        Map<Long, Integer> map = new HashMap<>();
        //	思路: 1.判断是否购买过专辑user_paid_album；true: trackId:1  2.判断是否购买过声音; true: trackId:1
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));
        if (null != userPaidAlbum) {
//            for (Long trackId : trackIdNeedPaidList) {
//                map.put(trackId, 1);
//            }
            return trackIdNeedPaidList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
        }
        //判断声音是否被购买
        LambdaQueryWrapper<UserPaidTrack> Wrapper = new LambdaQueryWrapper<>();
        Wrapper.eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, trackIdNeedPaidList);
        //购买的声音
        List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(Wrapper);
        //所有需要购买的声音全部赋值为0
        map = trackIdNeedPaidList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 0));
        if (!CollectionUtils.isEmpty(userPaidTracks)) {
            for (UserPaidTrack userPaidTrack : userPaidTracks) {
                map.put(userPaidTrack.getTrackId(), 1);
            }
        }
        return map;
    }

    @Override
    public Boolean isPaidAlbum(Long userId, Long albumId) {
        return null != userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId));


    }

    @Override
    public List<Long> findUserPaidTrackList(Long userId, Long albumId) {
        //  查看用户已购买当前专辑的声音Id集合
        List<Long> trackIdList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId))
                .stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        //  返回数据
        return trackIdList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        //判断购买的类型user_paid_album user_paid_track user_paid_vip
        try {
            if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
                //保存专辑
                //判断用户是否购买专辑
                LambdaQueryWrapper<UserPaidAlbum> wrapper = new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId())
                        .eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0));
                UserPaidAlbum userPaidAlbum = this.userPaidAlbumMapper.selectOne(wrapper);
                if (null != userPaidAlbum) {
                    //  说这个用户已经购买过了，则抛出异常
                    throw new RuntimeException("用户已经购买了此专辑！");
                }
                userPaidAlbum = new UserPaidAlbum();
                userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
                userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
                userPaidAlbumMapper.insert(userPaidAlbum);

            } else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
                //保存声音
                List<Long> itemIdList = userPaidRecordVo.getItemIdList();
                //  通过声音Id获取到声音对象;
                Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(itemIdList.get(0));
                Assert.notNull(trackInfoResult, "获取声音失败");
                TrackInfo trackInfo = trackInfoResult.getData();
                Long albumId = trackInfo.getAlbumId();
                //查询当前专辑声音中的是否被购买
                List<Long> userPaidTrackList = this.findUserPaidTrackList(userPaidRecordVo.getUserId(), albumId);
                for (Long trackId : itemIdList) {
                    if (userPaidTrackList.contains(trackId)) {
                        //  退钱！远程调用：记录有几条声音;albumId-->albumInfo.getPrice();
                        log.info("用户已经购买了此声音！");
                        continue;
                    }
                    UserPaidTrack userPaidTrack = new UserPaidTrack();
                    userPaidTrack.setUserId(userPaidRecordVo.getUserId());
                    userPaidTrack.setAlbumId(albumId);
                    userPaidTrack.setTrackId(trackId);
                    userPaidTrackMapper.insert(userPaidTrack);
                }

            } else {
                //保存vip
                UserVipService userVipService = new UserVipService();
                //vip可以重复购买
                //1.通过页面可以指定购买的时长;
                Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
                //获取购买的月份  通过这个Id 查询购买时长;
                VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
                Integer serviceMonth = vipServiceConfig.getServiceMonth();
                //2.判断用户是否已经购买
                UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
                if (1 == userInfo.getIsVip() && userInfo.getVipExpireTime().after(new Date())) {
                    //续费 在原来的时间上架服务月数
                    LocalDateTime localDateTime = new LocalDateTime(userInfo.getVipExpireTime()).plusMonths(serviceMonth);
                    System.out.println("续期时间:\t" + localDateTime.toDate());
                    userVipService.setExpireTime(localDateTime.toDate());
                } else {
                    //购买
                    LocalDateTime localDateTime = new LocalDateTime(new Date()).plusMonths(serviceMonth);
                    System.out.println("过期时间:\t" + localDateTime.toDate());
                    userVipService.setExpireTime(localDateTime.toDate());
                }
                //赋值
                userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
                userVipService.setUserId(userPaidRecordVo.getUserId());
                userVipService.setStartTime(new Date());
                //保存数据
                userVipServiceMapper.insert(userVipService);
                //更新用户信息
                userInfo.setIsVip(1);
                userInfo.setVipExpireTime(userVipService.getExpireTime());
                userInfoMapper.updateById(userInfo);
            }
            return true;
        } catch (RuntimeException e) {
            //  有异常信息.
            log.error(e.getMessage(), e);
            return false;
        }
    }
//        判断购买类型：
//        try {
//            if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
//                //  专辑 user_paid_album
//                //  利用userId,albumId 查询数据如果没有，则插入否则返回;
//                LambdaQueryWrapper<UserPaidAlbum> wrapper = new LambdaQueryWrapper<>();
//                wrapper.eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId()).eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0));
//                UserPaidAlbum userPaidAlbum = this.userPaidAlbumMapper.selectOne(wrapper);
//                //  判断当前对象是否为空
//                if (null != userPaidAlbum) {
//                    //  说这个用户已经购买过了，则抛出异常
//                    throw new RuntimeException("用户已经购买了此专辑！");
//                }
//                userPaidAlbum = new UserPaidAlbum();
//                //  赋值：
//                userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
//                userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
//                userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
//                //  保存数据;
//                userPaidAlbumMapper.insert(userPaidAlbum);
//
//            } else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
//                //  声音 user_paid_track
//                //  1.  将购买的声音Id保存到 user_paid_track中！
//                List<Long> itemIdList = userPaidRecordVo.getItemIdList();
//                //  通过声音Id获取到声音对象;
//                Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(itemIdList.get(0));
//                Assert.notNull(trackInfoResult, "查询声音信息失败！");
//                TrackInfo trackInfo = trackInfoResult.getData();
//                Long albumId = trackInfo.getAlbumId();
//                //  2.  查询当前用户是否购买过当前专辑对应的声音：
//                List<Long> userPaidTrackList = this.findUserPaidTrackList(userPaidRecordVo.getUserId(), albumId);
//                //  3.  需要比较;
//                for (Long trackId : itemIdList) {
//                    //  判断
//                    if (userPaidTrackList.contains(trackId)) {
//                        //  退钱！远程调用：记录有几条声音;albumId-->albumInfo.getPrice();
//                        log.info("用户已经购买了此声音！");
//                        continue;
//                    }
//                    //  创建对象
//                    UserPaidTrack userPaidTrack = new UserPaidTrack();
//                    userPaidTrack.setUserId(userPaidRecordVo.getUserId());
//                    userPaidTrack.setTrackId(trackId);
//                    userPaidTrack.setAlbumId(albumId);
//                    userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
//                    userPaidTrackMapper.insert(userPaidTrack);
//                }
//            } else {
//                //  vip user_vip_service
//                UserVipService userVipService = new UserVipService();
//                //  vip 能够重复购买!
//                //  1.  先通过页面传递的数据，知道要购买时长;
//                Long vipServiceConfigId = userPaidRecordVo.getItemIdList().get(0);
//                //  通过这个Id 查询购买时长;
//                VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(vipServiceConfigId);
//                Integer serviceMonth = vipServiceConfig.getServiceMonth();
//                //  2.  判断当前这个用户是否是vip；考虑续期的问题。 如果有续期还需更新 user_info 表; 如果没有续期，更新用户的is_vip字段; 1
//                UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
//                //  声明一个时间对象;
//                Date currentTime = new Date();
//                //  判断
//                if (1 == userInfo.getIsVip() && userInfo.getVipExpireTime().after(new Date())) {
//                    //  续期; 在原来过期时间基础上加上服务月数;
//                    LocalDateTime localDateTime = new LocalDateTime(userInfo.getVipExpireTime()).plusMonths(serviceMonth);
//                    //  userInfo.setVipExpireTime(localDateTime.toDate());
//                    System.out.println("续期时间:\t" + localDateTime.toDate());
//                    userVipService.setExpireTime(localDateTime.toDate());
//                } else {
//                    //  在当前系统时间基础上加服务月数;
//                    LocalDateTime localDateTime = new LocalDateTime(currentTime).plusMonths(serviceMonth);
//                    System.out.println("过期时间:\t" + localDateTime.toDate());
//                    userVipService.setExpireTime(localDateTime.toDate());
//                }
//                //  赋值：
//                userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
//                userVipService.setUserId(userPaidRecordVo.getUserId());
//                userVipService.setStartTime(currentTime);
//                //  保存的数据;
//                userVipServiceMapper.insert(userVipService);
//                //  更新用户信息表;
//                userInfo.setVipExpireTime(userVipService.getExpireTime());
//                userInfo.setIsVip(1);
//                userInfoMapper.updateById(userInfo);
//            }
//            //  没有异常返回true;
//            return true;
//        } catch (RuntimeException e) {
//            //  有异常信息.
//            log.error(e.getMessage(), e);
//            return false;
//        }
//    }
}
